/**
 * 使用三段式状态机来做数码管驱动
 */
module SEG_DRIVER (
    input       wire                clk_50M,    //必须是50M时钟，否则下面的时间不对
    input       wire                rst_n,      //低电平复位
    input       wire        [23:0]  number,
    input       wire                is_dec,     //数字是否显示为十进制，0：否，1：是
    output      reg         [5:0]   sel,
    output      reg         [7:0]   seg
);

wire overflow;//溢出标志
wire [27:0] bcdNumber;
wire [23:0] localVariableNumber;

assign localVariableNumber = is_dec ? bcdNumber : number;
assign overflow = (number>999999) ? 1'b1: 1'b0;

BCD # (
    .WIDTH                          (24)
)
BCD_inst (
    .hex                            (number),
    .bcd                            (bcdNumber)
);

reg [2:0] cstate;//当前状态
reg [2:0] nstate;//下一个状态
localparam T_1ms = 16'd50_000;//1ms切换一个数码管
reg [15:0] cnt;

//【1】状态跳转
always@(posedge clk_50M or negedge rst_n) begin
    if(rst_n == 0)
        begin
            cstate<=0;
            cnt<=0;
        end
    else
        begin
            cstate<= nstate;
            if(cnt>=T_1ms-1)
                cnt<=0;
            else
                cnt<= cnt + 1;
        end     
end

//【2】下一个状态判断（组合逻辑）
always @ (*) begin
    if (!rst_n)
        nstate = 0;
    else
        case(cstate)
            0   :  if(cnt ==T_1ms - 1)
                        if(localVariableNumber[23:4] >0)  
                            nstate=1;
                        else
                            nstate = 0; //此处可不可以为 nstate = nstate ? 待实验     不行！
                    else
                        nstate =0;
                        
            1   :  if(cnt ==T_1ms - 1) 
                        if(localVariableNumber[23:8] >0)
                            nstate = 2;
                        else
                            nstate = 0;
                    else
                        nstate = 1;
                        
            2   :  if(cnt ==T_1ms - 1)
                        if( localVariableNumber[23:12] >0)
                            nstate = 3;
                        else
                            nstate = 0;
                    else
                        nstate = 2;
                        
            3   :  if(cnt ==T_1ms - 1)
                        if(localVariableNumber[23:16] >0)
                            nstate = 4;
                        else
                            nstate = 0;
                    else
                        nstate = 3;
                        
            4   :  if(cnt ==T_1ms - 1)
                        if(localVariableNumber[23:20] >0)
                            nstate = 5;
                        else
                            nstate = 0;
                    else
                        nstate = 4;
                        
            5   :  if(cnt ==T_1ms - 1)
                        nstate = 0;
                    else
                        nstate = 5;
                        
            default   :    nstate = 1;
        endcase            
end

//【3】各个状态下的动作（可以组合也可以时序）
reg [3:0] value;
always @ (*) begin//posedge clk_50M or negedge rst_n
    if(rst_n == 0) begin
        sel = 0;
        value = 0;
    end
    else
        if (overflow)
            sel = 6'b000_000;//溢出，让所有数码管显示“-”
        else
            case(cstate)
                0 : begin
                        sel = 6'b111_110; //选择最右边数码管。PRA040,PRX100,006,025 sel都是低电平有效
                        value = localVariableNumber[3:0];
                    end
                1 : begin
                        sel = 6'b111_101;
                        value = localVariableNumber[7:4];
                    end
                2 : begin
                        sel = 6'b111_011;
                        value = localVariableNumber[11:8];
                    end
                3 : begin
                        sel = 6'b110_111;
                        value = localVariableNumber[15:12];
                    end
                4 : begin
                        sel = 6'b101_111;
                        value = localVariableNumber[19:16];
                    end
                5 : begin
                    sel = 6'b011_111;
                    value = localVariableNumber[23:20];
                    end
                default : begin
                        sel = 6'b111_110;
                        value = localVariableNumber[3:0];
                    end                         
            endcase
end

//【4】数码管seg的输出
always@(*)begin
    if(rst_n == 0)
        seg=8'b00000000;
    else
        if(overflow)
            seg=8'b10111111;//溢出显示为“-”
        else
            case(value)
                0  : seg=8'b11000000;// 0
                1  : seg=8'b11111001;// 1
                2  : seg=8'b10100100;// 2
                3  : seg=8'b10110000;// 3
                4  : seg=8'b10011001;// 4
                5  : seg=8'b10010010;// 5
                6  : seg=8'b10000010;// 6
                7  : seg=8'b11111000;// 7
                8  : seg=8'b10000000;// 8
                9  : seg=8'b10010000;// 9
                10 : seg=8'b10100000;// a
                11 : seg=8'b10000011;// b
                12 : seg=8'b11000110;// c
                13 : seg=8'b10100001;// d
                14 : seg=8'b10000110;// e
                15 : seg=8'b10001110;// f
                default : seg=8'b00000000;
            endcase
end

endmodule
